package com.eternal.log.model;

import android.app.Application;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.paging.DataSource;
import androidx.paging.LivePagedListBuilder;
import androidx.paging.PagedList;
import androidx.paging.PositionalDataSource;
import androidx.annotation.NonNull;
import android.text.TextUtils;
import android.view.View;

import com.eternal.base.LivePagedBuilder;
import com.eternal.base.concat.DeviceModel;
import com.eternal.base.concat.LogExtra;
import com.eternal.base.data.LogRepository;
import com.eternal.base.database.entity.Log;
import com.eternal.base.global.ActivityEvent;
import com.eternal.framework.bus.Messenger;
import com.eternal.framework.bus.RxBus;
import com.eternal.framework.component.BaseViewModel;
import com.eternal.framework.utils.GsonUtils;
import com.eternal.framework.utils.KLog;
import com.eternal.framework.utils.RxUtils;
import com.eternal.framework.utils.SPUtils;
import com.eternal.log.LogCFragment;
import com.eternal.log.R;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import io.reactivex.Single;
import io.reactivex.SingleEmitter;
import io.reactivex.SingleOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

public class LogCModel extends BaseViewModel {
    public LogCModel(@NonNull Application application) {
        super(application);
        show.setValue(true);
    }

    public String mac;

    public MutableLiveData<Boolean> show=new MutableLiveData<>();
    public MutableLiveData<Boolean> highTmpSwitch=new MutableLiveData<>();
    public MutableLiveData<Boolean> lowTmpSwitch=new MutableLiveData<>();
    public MutableLiveData<Boolean> highHumSwitch=new MutableLiveData<>();
    public MutableLiveData<Boolean> lowHumSwitch=new MutableLiveData<>();
    public LiveData<PagedList<Log>> logs;

    private LogRepository repository;

    public View.OnClickListener onName=new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(show.getValue()==Boolean.TRUE){
                show.setValue(false);
            }else{
                show.setValue(true);
            }
        }
    };

    public View.OnClickListener onFilter=new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int id = v.getId();
            if (id == R.id.tv_high_tmp) {
                changeState(highTmpSwitch);
            } else if (id == R.id.tv_low_tmp) {
                changeState(lowTmpSwitch);
            } else if (id == R.id.tv_high_hum) {
                changeState(highHumSwitch);
            } else if (id == R.id.tv_low_hum) {
                changeState(lowHumSwitch);
            }
        }
    };

    private void changeState(MutableLiveData<Boolean> data){
        data.setValue(!data.getValue());
        Messenger.getDefault().sendNoMsg(LogCFragment.REFRESH_LOG);
    }

    public void refresh(){
        logs=getSource();
    }

    public Single<LogExtra> init(LogRepository repository, final String mac, byte model){
        all();
        addSubscribe(Single.create(new SingleOnSubscribe<String>() {
            @Override
            public void subscribe(@io.reactivex.annotations.NonNull SingleEmitter<String> emitter) throws Exception {
                String typesString = SPUtils.getInstance().getString(ActivityEvent.SHARED_PREFERENCES_KEY_LOG_CHECKED_TYPES+mac);
                emitter.onSuccess(typesString);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<String>() {
            @Override
            public void accept(String typesString) throws Exception {
                List<Byte> types;

                if (TextUtils.isEmpty(typesString)) {
                    Byte [] allType = {1,2,3,4,5,6};
                    types = Arrays.asList(allType);
                } else {
                    types = GsonUtils.getList(typesString,Byte.class);
                }
                if (types != null) {
                    if(types.contains((byte) 1)){
                        highTmpSwitch.setValue(true);
                    }
                    if(types.contains((byte) 2)){
                        lowTmpSwitch.setValue(true);
                    }
                    if(types.contains((byte) 4)){
                        highHumSwitch.setValue(true);
                    }
                    if(types.contains((byte) 5)){
                        lowHumSwitch.setValue(true);
                    }
                }
                logs=getSource();
            }
        }));
        this.mac=mac;
        this.repository=repository;

        return getExtra();
    }

    private LiveData<PagedList<Log>> getSource(){
        List<Byte> types = new ArrayList<>(6);
        boolean tmp = false, hum = false;
        if (highTmpSwitch.getValue() == Boolean.TRUE) {
            types.add((byte) 0x1);
            tmp = true;
        }
        if (lowTmpSwitch.getValue() == Boolean.TRUE) {
            types.add((byte) 0x2);
            tmp = true;
        }
        if (highHumSwitch.getValue() == Boolean.TRUE) {
            types.add((byte) 0x4);
            hum = true;
        }
        if (lowHumSwitch.getValue() == Boolean.TRUE) {
            types.add((byte) 0x5);
            hum = true;
        }
        if (tmp) {
            types.add((byte) 0x3);
        }
        if (hum) {
            types.add((byte) 0x06);
        }
        SPUtils.getInstance().put(ActivityEvent.SHARED_PREFERENCES_KEY_LOG_CHECKED_TYPES+mac, GsonUtils.toJson(types));
        if(types.size()==0){
            return new LivePagedBuilder<>(new EmptyFactory(),
                    new PagedList.Config.Builder()
                            .setPageSize(12)
                            .setInitialLoadSizeHint(0)
                            .setEnablePlaceholders(false)
                            .build()).build();
        }

        return new LivePagedBuilder<>(repository.getLogFactory(mac, types),
                new PagedList.Config.Builder()
                        .setPageSize(15)
                        .setInitialLoadSizeHint(45)
                        .setEnablePlaceholders(false)
                        .build()).build();
    }

    private void all(){
        highTmpSwitch.setValue(false);
        lowTmpSwitch.setValue(false);
        highHumSwitch.setValue(false);
        lowHumSwitch.setValue(false);
    }

    public void resetTime(){
        repository.resetCTime(mac)
                .compose(RxUtils.bindToLifecycle(getLifecycleProvider()))
                .subscribeOn(Schedulers.io())
                .subscribe();
    }

    static class EmptyFactory extends DataSource.Factory<Integer, Log> {
        static final List<Log> empty=new ArrayList<>();
        @Override
        public DataSource<Integer, Log> create() {
            return new PositionalDataSource<Log>() {
                @Override
                public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<Log> callback) {
                    callback.onResult(empty, params.requestedStartPosition);
                }

                @Override
                public void loadRange(@NonNull LoadRangeParams params, @NonNull LoadRangeCallback<Log> callback) {
                    callback.onResult(empty);
                }
            };
        }
    }

    public Single<LogExtra> getExtra(){
        return repository.getExtra(mac);
    }
}
